<!doctype html>
<html lang="en">
  <head>
    <title>SSO</title>
  </head>
  <body>
    <div
      id="sso-config-page"
      data-role="page"
      class="page type-interior pluginConfigurationPage esqConfigurationPage"
      data-controller="__plugin/SSO-Auth.js"
    >
      <div data-role="content">
        <div class="content-primary">
          <div class="sectionTitleContainer flex align-items-center">
            <h2 class="sectionTitle">SSO Settings:</h2>
            <a
              is="emby-button"
              class="raised button-alt headerHelpButton"
              target="_blank"
              href="https://github.com/9p4/jellyfin-plugin-sso"
              >${Help}</a
            >
          </div>
          <p>
            <i>Note:</i>
            Making changes to this configuration requires a restart of Jellyfin.
            <br />
            This plug-in is in early development, not all configuration options
            have been implented in the UI, for example, SAML provider
            configuration has not been implemented.
            <br />
            See the
            <a
              is="emby-linkbutton"
              href="https://github.com/9p4/jellyfin-plugin-sso"
              class="button-link"
              >help page</a
            >
            and
            <a
              is="emby-linkbutton"
              href="https://github.com/9p4/jellyfin-plugin-sso/projects/1"
              class="button-link"
              >roadmap
            </a>
            for more information.
            <br />
            To allow users to manage their own SSO accounts, including linking
            SSO providers, and removing existing links, they need to visit
            <a
              is="emby-linkbutton"
              id="sso-self-service-link"
              class="button-link"
              >the self service page </a
            >. <br />
            You can use
            <a
              is="emby-linkbutton"
              href="https://jellyfin.org/docs/general/clients/web-config.html#custom-menu-links"
              class="button-link"
              >custom menu links
            </a>
            to accomplish this.
          </p>

          <form id="sso-load-config" class="esqConfigurationForm">
            <div
              class="verticalSection"
              is="emby-collapse"
              title="Select Existing Provider to Modify"
            >
              <div class="collapseContent">
                <div class="selectContainer">
                  <label class="selectLabel" for="selectProvider"
                    >Name of OpenID Provider:
                  </label>
                  <select
                    is="emby-select"
                    id="selectProvider"
                    name="selectProvider"
                    class="emby-select-withcolor emby-select"
                  ></select>
                  <div class="selectArrowContainer">
                    <div style="visibility: hidden; display: none">0</div>
                    <span
                      class="selectArrow material-icons keyboard_arrow_down"
                      aria-hidden="true"
                    ></span>
                  </div>
                </div>

                <button
                  id="LoadProvider"
                  is="emby-button"
                  type="button"
                  class="raised button-submit block emby-button"
                >
                  <span>Load Provider</span>
                </button>

                <button
                  id="DeleteProvider"
                  is="emby-button"
                  type="button"
                  class="raised button-delete block emby-button"
                >
                  <span>Delete Provider</span>
                </button>
              </div>
            </div>
          </form>

          <form id="sso-new-oidc-provider" class="esqConfigurationForm">
            <div
              is="emby-collapse"
              data-expanded="true"
              title="Add / Update Provider Configuration"
              class="verticalSection verticalSection-extrabottompadding"
            >
              <div class="collapseContent">
                <div class="inputContainer">
                  <label
                    class="inputLabel inputLabelUnfocused"
                    for="OidProviderName"
                    >Name of OpenID Provider:</label
                  >
                  <input
                    is="emby-input"
                    id="OidProviderName"
                    required=""
                    type="text"
                    class="sso-text"
                  />
                  <div class="fieldDescription">
                    The name used by Jellyfin to identify the OpenID provider.
                    <br />
                    If an OpenID provider with a matching name does not exist, a
                    new provider with this name will be created.
                    <br />
                    If an OpenID provider with a matching name already exists,
                    the settings for that provider will be updated.
                  </div>
                </div>
                <div class="inputContainer">
                  <label
                    class="inputLabel inputLabelUnfocused"
                    for="OidEndpoint"
                    >OpenID Endpoint:</label
                  >
                  <input
                    is="emby-input"
                    id="OidEndpoint"
                    required=""
                    type="text"
                    class="sso-text"
                  />
                  <div class="fieldDescription">
                    The OpenID endpoint. Must have a .well-known path available.
                  </div>
                </div>

                <div class="inputContainer">
                  <label
                    class="inputLabel inputLabelUnfocused"
                    for="OidClientId"
                    >OpenID Client ID:</label
                  >
                  <input
                    is="emby-input"
                    id="OidClientId"
                    required=""
                    type="text"
                    class="sso-text"
                  />
                  <div class="fieldDescription">
                    The OpenID client ID, for this media server instance. This
                    is configured on the OIDC provider to uniquely identify
                    <strong>this</strong> Jellyfin instance.
                  </div>
                </div>
                <div class="inputContainer">
                  <label class="inputLabel inputLabelUnfocused" for="OidSecret"
                    >OpenID client secret:</label
                  >
                  <input
                    is="emby-input"
                    id="OidSecret"
                    required=""
                    type="text"
                    class="sso-text"
                  />
                  <div class="fieldDescription">
                    The OpenID client secret. Randomly generated & shared.
                  </div>
                </div>

                <div
                  class="checkboxContainer checkboxContainer-withDescription"
                >
                  <label>
                    <input
                      is="emby-checkbox"
                      id="Enabled"
                      name="Enabled"
                      type="checkbox"
                      class="sso-toggle"
                    />
                    <span>Enabled</span>
                  </label>
                </div>

                <div
                  class="checkboxContainer checkboxContainer-withDescription"
                >
                  <label>
                    <input
                      is="emby-checkbox"
                      id="EnableAuthorization"
                      name="EnableAuthorization"
                      type="checkbox"
                      class="sso-toggle"
                    />
                    <span>Enable Authorization by Plugin</span>
                  </label>
                  <div class="fieldDescription checkboxFieldDescription">
                    Determines if the plugin sets permissions for the user.
                    <br />
                    If false, the user will start with no permissions and an
                    administrator will add permissions.
                    <br />
                    The permissions of existing users will not be rewritten on
                    subsequent logins.
                  </div>
                </div>

                <div
                  class="checkboxContainer checkboxContainer-withDescription"
                >
                  <label>
                    <input
                      is="emby-checkbox"
                      id="EnableAllFolders"
                      name="EnableAllFolders"
                      type="checkbox"
                      class="sso-toggle"
                    />
                    <span>Enable All Folders</span>
                  </label>
                  <div class="fieldDescription checkboxFieldDescription">
                    If enabled, all libraries will be accessible to any user
                    that logs in through this provider.
                  </div>
                </div>
                <div class="inputContainer">
                  <label
                    class="inputLabel inputLabelUnfocused"
                    for="EnabledFolders"
                    >Enabled Folders:</label
                  >
                  <div
                    id="EnabledFolders"
                    class="checkboxList paperList checkboxList-paperList sso-folder-list sso-bordered-list"
                  ></div>
                  <div class="fieldDescription">
                    Determines which libraries will be accessible to a user that
                    logs in through this provider.
                    <br />
                    If <strong>"Enable All Folders"</strong> is checked, then
                    this has no effect.
                  </div>
                </div>

                <div class="inputContainer">
                  <label class="inputLabel inputLabelUnfocused" for="Roles"
                    >Roles:</label
                  >
                  <textarea
                    is="emby-textarea"
                    id="Roles"
                    type="text"
                    class="sso-line-list emby-textarea"
                  ></textarea>
                  <div class="fieldDescription">
                    A list of roles, one role per-line to look for in the OpenID
                    response.
                    <br />
                    If a user has any of these roles, then the user is
                    authenticated. This validates the OpenID response against
                    the claim set in <strong>"RoleClaim"</strong>.
                    <br />
                    Leave blank to disable role checking.
                  </div>
                </div>

                <div class="inputContainer">
                  <label class="inputLabel inputLabelUnfocused" for="AdminRoles"
                    >Admin Roles:</label
                  >
                  <textarea
                    is="emby-textarea"
                    id="AdminRoles"
                    type="text"
                    class="sso-line-list emby-textarea"
                  ></textarea>
                  <div class="fieldDescription">
                    A list of roles, one role per-line to look for in the OpenID
                    response.
                    <br />
                    Like <strong>"Roles"</strong>, but having any of the roles
                    confers admin privilege.
                    <br />
                    If unset will not grant admin privileges.
                  </div>
                </div>

                <div
                  class="checkboxContainer checkboxContainer-withDescription"
                >
                  <label>
                    <input
                      is="emby-checkbox"
                      id="EnableFolderRoles"
                      name="EnableFolderRoles"
                      type="checkbox"
                      class="sso-toggle"
                    />
                    <span>Enable Role-Based Folder Access:</span>
                  </label>
                  <div class="fieldDescription checkboxFieldDescription">
                    Determines if user roles should be used to control library
                    access.
                  </div>
                </div>

                <div class="inputContainer">
                  <label
                    class="inputLabel inputLabelUnfocused"
                    for="FolderRoleMapping"
                    >Folder Role Mapping:</label
                  >
                  <button
                    is="emby-button"
                    id="AddRoleMapping"
                    type="button"
                    class="fab btnAddFolder submit"
                    title="${Add}"
                  >
                    <span class="material-icons add" aria-hidden="true"></span>
                  </button>
                  <div id="FolderRoleMapping" class="sso-role-map"></div>
                  <div class="fieldDescription">
                    Map roles (given by <strong>"Role Claim"</strong>) to lists
                    of libraries. If a user has a given role, they will have
                    access to the corresponding libraries. If
                    <strong>"Enable Role-Based Folder Access"</strong> is
                    disabled, has no effect.
                  </div>
                </div>

                <div
                  class="checkboxContainer checkboxContainer-withDescription"
                >
                  <label>
                    <input
                      is="emby-checkbox"
                      id="EnableLiveTvRoles"
                      name="EnableLiveTvRoles"
                      type="checkbox"
                      class="sso-toggle"
                    />
                    <span>Enable Live TV RBAC</span>
                  </label>
                  <div class="fieldDescription checkboxFieldDescription">
                    Determines whether the roles will be used to grant Live TV
                    privileges.
                  </div>
                </div>

                <div class="inputContainer">
                  <label
                    class="inputLabel inputLabelUnfocused"
                    for="LiveTvRoles"
                    >Live TV Roles:</label
                  >
                  <textarea
                    is="emby-textarea"
                    id="LiveTvRoles"
                    type="text"
                    class="sso-line-list emby-textarea"
                  ></textarea>
                  <div class="fieldDescription">
                    A list of roles, one role per-line to look for in the OpenID
                    response.
                    <br />
                    Like <strong>"Roles"</strong>, but having any of the roles
                    confers Live TV privileges.
                  </div>
                </div>

                <div class="inputContainer">
                  <label
                    class="inputLabel inputLabelUnfocused"
                    for="LiveTvManagementRoles"
                    >Live TV Management Roles:</label
                  >
                  <textarea
                    is="emby-textarea"
                    id="LiveTvManagementRoles"
                    type="text"
                    class="sso-line-list emby-textarea"
                  ></textarea>
                  <div class="fieldDescription">
                    A list of roles, one role per-line to look for in the OpenID
                    response.
                    <br />
                    Like <strong>"Roles"</strong>, but having any of the roles
                    confers Live TV administration privileges.
                  </div>
                </div>

                <div
                  class="checkboxContainer checkboxContainer-withDescription"
                >
                  <label>
                    <input
                      is="emby-checkbox"
                      id="EnableLiveTv"
                      name="EnableLiveTv"
                      type="checkbox"
                      class="sso-toggle"
                    />
                    <span>Enable Live TV Access By Default</span>
                  </label>
                  <div class="fieldDescription checkboxFieldDescription">
                    Determines whether the user can view Live TV by default.
                    <br />
                    This value is still used if <strong>Live TV RBAC</strong> is
                    enabled!
                  </div>
                </div>

                <div
                  class="checkboxContainer checkboxContainer-withDescription"
                >
                  <label>
                    <input
                      is="emby-checkbox"
                      id="EnableLiveTvManagement"
                      name="EnableLiveTvManagement"
                      type="checkbox"
                      class="sso-toggle"
                    />
                    <span>Enable Live TV Management By Default</span>
                  </label>
                  <div class="fieldDescription checkboxFieldDescription">
                    Determines whether the user can manage Live TV by default.
                    <br />
                    This value is still used if <strong>Live TV RBAC</strong> is
                    enabled!
                  </div>
                </div>

                <div class="inputContainer">
                  <label class="inputLabel inputLabelUnfocused" for="RoleClaim"
                    >Role Claim:</label
                  >
                  <input
                    is="emby-input"
                    id="RoleClaim"
                    required=""
                    type="text"
                    class="sso-text"
                  />
                  <div class="fieldDescription">
                    This is the value in the OpenID response to check for roles.
                    The first element is the claim type, the subsequent values
                    are to parse the JSON of the claim value. Use a
                    <code>"\."</code> to denote a literal ".". This expects a
                    list of strings from the OIDC server.
                    <br />
                    For Keycloak, it is <code>realm_access.roles</code> by
                    default.
                    <br />
                    For Authelia, it is <code>groups</code>
                  </div>
                </div>

                <div class="inputContainer">
                  <label class="inputLabel inputLabelUnfocused" for="OidScopes"
                    >Request Additional Scopes:</label
                  >
                  <textarea
                    is="emby-textarea"
                    id="OidScopes"
                    required=""
                    type="text"
                    class="sso-line-list emby-textarea"
                  ></textarea>
                  <div class="fieldDescription">
                    Specify additional scopes to include in the OIDC request.
                    <br />
                    One scope per line, each line should contain a scope name to
                    include in the OIDC request.
                    <br />
                    For some OIDC providers (For example,
                    <a
                      is="emby-linkbutton"
                      href="https://github.com/9p4/jellyfin-plugin-sso/issues/23#issuecomment-1112237616"
                      class="button-link"
                      >authelia</a
                    >), additional scopes may be required in order to validate
                    group membership in role claim.
                    <br />
                    Leave blank to only request the default scopes.
                  </div>
                </div>

                <div class="inputContainer">
                  <label
                    class="inputLabel inputLabelUnfocused"
                    for="DefaultProvider"
                    >Set default Provider:</label
                  >
                  <input
                    is="emby-input"
                    id="DefaultProvider"
                    type="text"
                    class="sso-text"
                  />
                  <div class="fieldDescription">
                    The set provider then gets assigned to the user after they
                    have logged in. If it is not set, nothing is changed. With
                    this, a user can login with SSO but is still able to log in
                    via other providers later.<br />A common option is
                    <code
                      >Jellyfin.Server.Implementations.Users.DefaultAuthenticationProvider</code
                    >
                    for the default provider.
                  </div>
                </div>

                <div class="inputContainer">
                  <label
                    class="inputLabel inputLabelUnfocused"
                    for="DefaultUsernameClaim"
                    >Set default username claim:</label
                  >
                  <input
                    is="emby-input"
                    id="DefaultUsernameClaim"
                    type="text"
                    class="sso-text"
                  />
                  <div class="fieldDescription">
                    The default username claim to use from OpenID by default. If
                    it is not set, it defaults to
                    <code>preferred_username</code>.
                  </div>
                </div>

                <div class="inputContainer">
                  <label
                    class="inputLabel inputLabelUnfocused"
                    for="AvatarUrlFormat"
                    >Set avatar url format</label
                  >
                  <input
                    is="emby-input"
                    id="AvatarUrlFormat"
                    type="text"
                    class="sso-text"
                  />
                  <div class="fieldDescription">
                    The url of the avatar with sso variable format: example :
                    <code>https://example.com/@{user_id}.png</code>
                  </div>
                </div>

                <div class="checkboxContainer">
                  <label>
                    <input
                      is="emby-checkbox"
                      id="DisableHttps"
                      name="DisableHttps"
                      type="checkbox"
                      class="sso-toggle"
                    />
                    <span>Disable OpenID HTTPS Discovery (Insecure)</span>
                  </label>
                  <div class="fieldDescription checkboxFieldDescription"></div>
                </div>

                <div class="checkboxContainer">
                  <label>
                    <input
                      is="emby-checkbox"
                      id="DisablePushedAuthorization"
                      name="DisablePushedAuthorization"
                      type="checkbox"
                      class="sso-toggle"
                    />
                    <span
                      >Disable Pushed Authorization (Insecure). May be needed
                      for Authelia.</span
                    >
                  </label>
                  <div class="fieldDescription checkboxFieldDescription"></div>
                </div>

                <div
                  class="checkboxContainer checkboxContainer-withDescription"
                >
                  <label>
                    <input
                      is="emby-checkbox"
                      id="DoNotValidateEndpoints"
                      name="DoNotValidateEndpoints"
                      type="checkbox"
                      class="sso-toggle"
                    />
                    <span>Do Not Validate OpenID Endpoints (Insecure)</span>
                  </label>
                  <div class="fieldDescription checkboxFieldDescription">
                    May be required for Google OpenID
                  </div>
                </div>
                <div class="checkboxContainer">
                  <label>
                    <input
                      is="emby-checkbox"
                      id="DoNotValidateIssuerName"
                      name="DoNotValidateIssuerName"
                      type="checkbox"
                      class="sso-toggle"
                    />
                    <span>Do Not Validate OpenID Issuer Name (Insecure)</span>
                  </label>
                </div>

                <div class="inputContainer">
                  <label class="inputLabel inputLabelUnfocused" for="RoleClaim"
                    >Scheme Override</label
                  >
                  <input
                    is="emby-input"
                    id="SchemeOverride"
                    type="text"
                    class="sso-text"
                  />
                  <div class="fieldDescription">
                    If the plugin is redirecting to an insecure URL, set this to
                    "https"
                  </div>
                </div>

                <div class="inputContainer">
                  <label class="inputLabel inputLabelUnfocused" for="RoleClaim"
                    >Port Override</label
                  >
                  <input
                    is="emby-input"
                    id="PortOverride"
                    type="text"
                    class="sso-text"
                  />
                  <div class="fieldDescription">
                    If the plugin is redirecting to an incorrect port, set this
                    to the appropiate port
                  </div>
                </div>

                <button
                  id="SaveProvider"
                  is="emby-button"
                  type="button"
                  class="raised button-submit block emby-button"
                >
                  <span>Save</span>
                </button>
              </div>
            </div>
          </form>
        </div>
      </div>
    </div>
  </body>
</html>
